//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#ifndef UTIL_HPP
#define UTIL_HPP

#include "resource.h"

// centers hwndChild within hwndParent
// if hwndParent is NULL, hwndChild is centered on the desktop
BOOL CenterWindow (HWND hwndChild, HWND hwndParent);

LPCTSTR LoadStringEx (int id);
BOOL IsValidIpAddress (LPCTSTR szIpString, LPTSTR &pszStr);
BOOL IsIpAddress (LPCTSTR szIpString);

#ifndef UNDER_CE
BOOL EncryptPassword(WCHAR szData[16], BYTE szOutputBuff[32]);
#else
#include <wincrypt.h>

BOOL EncryptPassword(WCHAR szData[16], DATA_BLOB *pDataOut);
#endif

BOOL SetRunOnBoot(BOOL bEnable);

//partially copied from ATL headers
/////////////////////////////////////////////////////////////////////////////
// Collection helpers - CSimpleArray

#define ALLOC_SCALE	20
template <class T>
class CSimpleArray
{
public:
	CSimpleArray() : _pT(NULL), _nCurSize(0), _nMaxSize(0)
	{}

	~CSimpleArray()		{	RemoveAll();	}

public:
	int GetSize() const		{	return _nCurSize;	}

	BOOL Add(T &t)
	{
		if (_nCurSize == _nMaxSize)
		{
			T *pT = (_pT) ? (T *)realloc(_pT, (_nMaxSize+ALLOC_SCALE)*sizeof(T)) : 
							(T *)malloc(ALLOC_SCALE*sizeof(T));
			if (!pT)
				return FALSE;

			_pT = pT;

			_nMaxSize += ALLOC_SCALE;
		}

		ASSERT(_pT);
		
		_pT[_nCurSize++] = t;
		return TRUE;
	}

	void RemoveAll()
	{
		if (_pT)
		{
			for (int i=0; i<_nCurSize; i++)
				_pT[i].~T();
			LocalFree(_pT);
		}

		_pT = NULL;
		_nCurSize = _nMaxSize = 0;
	}

	BOOL Remove(T& t)
	{
		for (int i=0; i<_nCurSize; i++)
		{
			if (_pT[i] == t)
			{
				_pT[i].~T();
				memmove((PBYTE)&_pT[i], (PBYTE)&_pT[i+1], (_nCurSize - i - 1)*sizeof(T));
				return TRUE;
			}
		}
		return FALSE;
	}

	T& operator[] (int nIndex) const
	{
		ASSERT(nIndex >= 0 && nIndex < _nCurSize);
		return _pT[nIndex];
	}

public:
	T	*_pT;
	int	_nCurSize;
	int _nMaxSize;
};

/////////////////////////////////////////////////////////////////////////////
// Message map

#define BEGIN_MSG_MAP(theClass) \
public: \
	virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult, DWORD dwMsgMapID = 0) \
	{ \
		BOOL bHandled = TRUE; \
		hWnd; \
		uMsg; \
		wParam; \
		lParam; \
		lResult; \
		bHandled; \
		switch(dwMsgMapID) \
		{ \
		case 0:

#define MESSAGE_HANDLER(msg, func) \
	if(uMsg == msg) \
	{ \
		bHandled = TRUE; \
		lResult = func(uMsg, wParam, lParam, bHandled); \
		if(bHandled) \
			return TRUE; \
	}

#define COMMAND_HANDLER(id, code, func) \
	if(uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \
	{ \
		bHandled = TRUE; \
		lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \
		if(bHandled) \
			return TRUE; \
	}

#define NOTIFY_HANDLER(id, cd, func) \
	if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \
	{ \
		bHandled = TRUE; \
		lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \
		if(bHandled) \
			return TRUE; \
	}

#define CHAIN_MSG_MAP(theChainClass) \
	{ \
		if(theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
			return TRUE; \
	}

#define END_MSG_MAP() \
			break; \
		default: \
			ASSERT(FALSE); \
			break; \
		} \
		return FALSE; \
	}

#endif // UTIL_HPP
